/*
 * @Author: 无聊 7989314+Hwz1997@user.noreply.gitee.com
 * @Date: 2025-06-30 17:00:44
 * @LastEditors: 无聊 7989314+Hwz1997@user.noreply.gitee.com
 * @LastEditTime: 2025-08-29 00:47:28
 * @FilePath: \keep_motion_api\models\menu.model.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const { escapeRegex } = require('@/utils');

// 菜单项模型
const menuSchema = new Schema({
  name: { type: String, required: true },
  path: String,
  icon: { type: String, default: 'Menu' },
  component: String,
  order:  { type: Number, default: 1 },
  hidden: { type: Boolean, default: false },
  children: [{
    type: Schema.Types.ObjectId,
    ref: 'Menu'
  }]
});

// 查询菜单（带分页）
menuSchema.statics.getMenu = async function (parentId, name = '', offset = 0, limit = 10) {
  try {
    if(parentId){
      const parentMenu = await this.findById(parentId);
      if (!parentMenu) return { rows: [], total: 0 };
      const query = { _id: { $in: parentMenu.children } };
      const pipeline = [
        { $match: query },
        // 添加haschildren属性：children数组长度>0则为true
        { $addFields: {
            hasChildren: { $gt: [{ $size: '$children' }, 0] }
          }
        },
        { $project: {
            _id: 1, name: 1, path: 1, icon: 1, component: 1,
            order: 1, hidden: 1, children: 1, hasChildren: 1
          }
        },
        { $sort: { order: 1 } }
      ];
      const rows = await this.aggregate(pipeline);
      const total = await this.countDocuments(query);
      return { rows, total };
    }
    const query = {};
    if (name) {
      const escapedName = escapeRegex(name);
      query.name = { $regex: escapedName, $options: 'i' };
    }
    // 聚合查询获取顶级菜单（未被任何菜单引用为子节点的菜单）
      const pipeline = [
        // 查找所有未作为子菜单被引用的菜单
        {
          $lookup: {
            from: 'menus',
            localField: '_id',
            foreignField: 'children',
            as: 'parentReferences'
          }
        },
        { $match: { parentReferences: { $size: 0 }, ...query } },
        { $project: { parentReferences: 0 } }, // 排除临时字段
        { $addFields: {
            hasChildren: { $gt: [{ $size: '$children' }, 0] }
          }
        },
        { $sort: { order: 1 } },
        { $skip: Number(offset) },
        { $limit: Number(limit) }
      ];
      // 执行聚合查询并获取总数
      const [rows, totalResult] = await Promise.all([
        this.aggregate(pipeline),
        this.aggregate([...pipeline.slice(0, 2), { $count: 'total' }])
      ]);
      return { 
        rows,
        total: totalResult.length > 0 ? totalResult[0].total : 0
      };
  } catch (error) {
    throw error;
  }
}

// 创建菜单
menuSchema.statics.createMenu = async function (menuData) {
  try {
    const { name, path, icon, component, order, parentId } = menuData;
    const menu = await this.create({ name, path, icon, component, order});
    if (parentId) await this.findByIdAndUpdate(parentId, {$push: { children: menu._id }});
    return menu;
  } catch (error) {
    throw error;
  }
}

// 更新菜单
menuSchema.statics.updateMenu = async function (id, menuData) {
  try {
    const { name, path, icon, component, order, hidden, children } = menuData;
    const menu = await this.findByIdAndUpdate(
      id,
      { name, path, icon, component, order, hidden, children },
      { new: true } // 返回更新后的文档
    );
    return menu;
  } catch (error) {
    throw error;
  }
}
// 删除菜单
menuSchema.statics.deleteMenu = async function (id) {
  try {
    // 先检查是否有子菜单    
    const menu = await this.findOneAndDelete(
      { _id: id, children: { $size: 0 } },
      { new: true }
    );
    if (menu) await this.updateMany({ children: id }, { $pull: { children: id } } );
    else {
      // 查询不存在或存在子菜单时返回友好错误
      const existingMenu = await this.findById(id);
      if (!existingMenu) throw new Error('菜单不存在'); 
      else if (existingMenu.children && existingMenu.children.length > 0) throw new Error('该菜单存在子菜单，无法删除');
    }
    return menu;
  } catch (error) {
    throw error;
  }
}
// 获取用户菜单
menuSchema.statics.getPath = async function (id) {
  try {
    const pipeline = [
      // 递归查询所有子菜单
      {
        $graphLookup: {
          from: 'menus',
          startWith: '$children',
          connectFromField: 'children',
          connectToField: '_id',
          as: 'allChildren'
        }
      },
      // 筛选非隐藏菜单
      { $match: { hidden: false } },
      // 筛选顶级菜单（未被任何菜单引用的）
      {
        $lookup: {
          from: 'menus',
          localField: '_id',
          foreignField: 'children',
          as: 'parentReferences'
        }
      },
      { $match: { parentReferences: { $size: 0 } } },
      { $project: { parentReferences: 0 } },
      // 构建嵌套结构
      {
        $addFields: {
          children: {
            $filter: {
              input: '$allChildren',
              as: 'child',
              cond: {
                $and: [
                  { $in: ['$$child._id', '$children'] },
                  { $eq: ['$$child.hidden', false] } // 新增子菜单隐藏过滤
                ]
              }
            }
          }
        }
      },
      { $project: { allChildren: 0 } },
      { $sort: { order: 1 } }
    ];
    // JavaScript后处理：递归排序子菜单
    const sortChildren = (menu) => {
      // 对子菜单按order升序排序
      menu.children.sort((a, b) => a.order - b.order);
      // 递归处理每个子菜单
      menu.children.forEach(sortChildren);
      return menu;
    };
    // 执行聚合查询
    const data = await this.aggregate(pipeline);
    // 对查询结果进行后处理
    const rows = data.map(sortChildren);
    return rows;
  } catch (error) {
    throw error;
  }
}

module.exports = mongoose.model('Menu', menuSchema);
